package com.maixy.studyonlineapi.utils;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * @author HuangLinWei
 * @since 2019/12/6
 */
public final class LocalDateTimeUtils {


    private LocalDateTimeUtils() {

    }

    public static final String TIME_MINUTE_FORMAT = "HH:mm";
    public static final String TIME_MINUTE_NO_COLON_FORMAT = "HHmm";
    public static final String TIME_MINUTE_SECOND_FORMAT = "HH:mm:ss";
    public static final String NORMAL_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String NORMAL_DATETIME_FORMAT_NO_SECOND = "yyyy-MM-dd HH:mm";
    public static final String DOT_DATETIME_FORMAT_NO_SECOND = "yyyy.MM.dd HH:mm";
    public static final String NORMAL_DATE = "yyyy-MM-dd";

    private static final ZoneId DEFAULT_ZONE = ZoneId.systemDefault();
    private static final DateTimeFormatter SIMPLE_HOUR_MINUTE_DATE_FORMATTER = DateTimeFormatter.ofPattern(TIME_MINUTE_FORMAT);
    private static final DateTimeFormatter SIMPLE_DATE_FORMATTER = DateTimeFormatter.ofPattern(TIME_MINUTE_SECOND_FORMAT);
    private static final DateTimeFormatter NORMAL_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(NORMAL_DATETIME_FORMAT);

    public static LocalDateTime parse(long timestamp) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        return LocalDateTime.ofInstant(instant, DEFAULT_ZONE);
    }

    public static LocalDateTime parse(String date) {
        return LocalDateTime.parse(date, NORMAL_DATETIME_FORMATTER);
    }


    public static LocalDateTime parse(String date, String format) {
        return LocalDateTime.parse(date, getDateTimeFormatterByPattern(format));
    }

    public static long toTimestamp(LocalDateTime localDateTime){
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant).getTime();
    }

    public static long getDayEndTimestamp(LocalDateTime localDateTime) {
        return localDateTime.withHour(23).withMinute(59).withSecond(59)
                .atZone(DEFAULT_ZONE).toInstant().toEpochMilli();
    }

    public static long getDayEndTimestamp(LocalDate localDate) {
        String todayEnd = localDate.toString() + " 23:59:59";
        return LocalDateTime.parse(todayEnd, NORMAL_DATETIME_FORMATTER)
                .atZone(DEFAULT_ZONE).toInstant().toEpochMilli();
    }

    public static long getDayStartTimestamp(LocalDate localDate) {
        String todayEnd = localDate.toString() + " 00:00:00";
        return LocalDateTime.parse(todayEnd, NORMAL_DATETIME_FORMATTER)
                .atZone(DEFAULT_ZONE).toInstant().toEpochMilli();
    }

    public static LocalDateTime getDayStartTime(LocalDate localDate) {
        String todayEnd = localDate.toString() + " 00:00:00";
        return LocalDateTime.parse(todayEnd, NORMAL_DATETIME_FORMATTER);
    }

    public static String format(long timestamp, String pattern) {
        LocalDateTime parse = parse(timestamp);
        DateTimeFormatter dateTimeFormatterByPattern = getDateTimeFormatterByPattern(pattern);
        return dateTimeFormatterByPattern.format(parse);
    }

    public static String format(LocalDateTime localDateTime, String pattern) {
        DateTimeFormatter dateTimeFormatterByPattern = getDateTimeFormatterByPattern(pattern);
        return dateTimeFormatterByPattern.format(localDateTime);
    }

    public static LocalDateTime of(long timestamp) {
        return Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static DateTimeFormatter getDateTimeFormatterByPattern(String pattern) {
        switch (pattern) {
            case TIME_MINUTE_FORMAT:
                return SIMPLE_HOUR_MINUTE_DATE_FORMATTER;
            default:
                return DateTimeFormatter.ofPattern(pattern);
        }
    }

    public static boolean isAtDay(LocalDate localDate, Long dayTimestamp) {
        long dayStartTimestamp = getDayStartTimestamp(localDate);
        long dayEndTimestamp = getDayEndTimestamp(localDate);
        return dayEndTimestamp > dayTimestamp && dayStartTimestamp < dayTimestamp;
    }

    /**
     * 计算今日还剩下多少秒
     * @return long
     */
    public static long todayHasSeconds () {
        LocalDateTime nowTime = LocalDateTime.now(DEFAULT_ZONE);
        LocalDateTime todayTimeEnd = LocalDateTime.parse(LocalDate.now(DEFAULT_ZONE).toString() + " 23:59:59", NORMAL_DATETIME_FORMATTER);
        return ChronoUnit.SECONDS.between(nowTime, todayTimeEnd);
    }

    /**
     * 根据LocalDate获得Date
     * @param date 某个日期
     * @return 某个日期的Date
     */
    public static Date getThisDateTime(LocalDate date) {
        LocalDateTime nowTime = LocalDateTime.now(DEFAULT_ZONE);
        String dateTime = date.toString()+ " " + LocalDateTimeUtils.format(nowTime, LocalDateTimeUtils.TIME_MINUTE_SECOND_FORMAT);
        LocalDateTime nwoDateTime = LocalDateTimeUtils.parse(dateTime);
        return Date.from(nwoDateTime.atZone(DEFAULT_ZONE).toInstant());
    }

    /**
     * 根据时间获得Date
     * @param time 某个时间段
     * @return 某个时间段的Date
     */
    public static Date getThisDateTime(String time) {
        LocalDateTime nowTime = LocalDateTime.now(DEFAULT_ZONE);
        String dateTime = LocalDateTimeUtils.format(nowTime, LocalDateTimeUtils.NORMAL_DATE)+ " " + time + ":00";
        LocalDateTime nwoDateTime = LocalDateTimeUtils.parse(dateTime);
        return Date.from(nwoDateTime.atZone(DEFAULT_ZONE).toInstant());
    }

    public static LocalDateTime dateToLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

}
